package sunyu.demo.mina;

import org.nutz.http.Header;
import org.nutz.http.Response;
import org.slf4j.Logger;
import sunyu.toolkit.core.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 国标协议工具类
 *
 * @author 孙宇
 */
public class ProtocolKit {

    private static final Logger logger = LogKit.getLogger();

    public static int 获得平台登入登出最后的流水号加1(String WEB_SESSION, String unitName) {
        Map<String, Object> params = new HashMap();
        params.put("query.pid.unitName&lis", unitName.trim());
        params.put("query.type&eq", 0);
        params.put("page", 1);
        params.put("rows", 1);
        params.put("sort", "id");
        params.put("order", "desc");
        Header header = Header.create();
        header.set("Cookie", "WEB_SESSION=" + WEB_SESSION);
        Response r = HttpKit.post("http://218.205.184.123:7070/sysPlatformEvent/datagrid.html", params, header);
        logger.debug("{}", r.getContent());
        String seqid = JsonKit.getProperty(r.getContent(), "rows[0].seqid", String.class);
        logger.debug("{}", seqid);
        if (StringKit.isNotBlank(seqid)) {
            return Integer.parseInt(seqid) + 1;
        }
        return 1;
    }

    public static String 报文解析(String datas, String WEB_SESSION) {
        Map<String, Object> params = new HashMap();
        params.put("datas", datas);
        Header header = Header.create();
        header.set("Cookie", "messageQuery%3Adatas=" + datas + "; WEB_SESSION=" + WEB_SESSION);
        Response r = HttpKit.post("http://218.205.184.123:7070/messageQuery/doParseStation.html", params, header);

        List<Map> dataJson = JsonKit.getProperty(r.getContent(), "data.dataJson", List.class);
        for (Map md : dataJson) {
            logger.debug("{}", md);
        }

        return r.getContent();
    }

    public static String 报文校验(String datas, String WEB_SESSION) {
        Map<String, Object> params = new HashMap();
        params.put("datas", datas);
        Header header = Header.create();
        header.set("Cookie", "messageQuery%3Adatas=" + datas + "; WEB_SESSION=" + WEB_SESSION);
        Response r = HttpKit.post("http://218.205.184.123:7070/messageQuery/doParseStation_check.html", params, header);

        List<Map> dataJson = JsonKit.getProperty(r.getContent(), "data.dataJson", List.class);
        if (dataJson.size() < 1) {
            logger.debug("校验通过");
        } else {
            logger.error("校验失败");
            for (Map md : dataJson) {
                logger.error("{}", md);
            }
        }

        return r.getContent();
    }

    /**
     * 信息上报
     *
     * @param 上报类型       命令标识.xxx
     * @param 唯一识别码      设备发送就用did，平台发送就用vin
     * @param timeString 数据采集时间(yyyyMMddHHmmss)
     * @param zcsj       整车数据
     * @param qddjsj     驱动电机数据
     * @param clwzsj     车辆位置数据
     * @param jzsj       极值数据
     * @param bjsj       报警数据
     * @return
     */
    public static byte[] 信息上报(byte[] 上报类型, String 唯一识别码, String timeString, 整车数据 zcsj, 驱动电机数据 qddjsj, 车辆位置数据 clwzsj, 极值数据 jzsj, 报警数据 bjsj, 发动机数据 fdjsj) {
        byte[] bytes = {};

        bytes = ByteKit.byteMerger(bytes, 起始符.b0);
        logger.debug("起始符=> {}", StringKit.bytes2hexString(起始符.b0));

        bytes = ByteKit.byteMerger(bytes, 上报类型);
        logger.debug("命令单元-命令标识=> {}", StringKit.bytes2hexString(上报类型));

        bytes = ByteKit.byteMerger(bytes, 应答标识.命令);
        logger.debug("命令单元-应答标识=> {}", StringKit.bytes2hexString(应答标识.命令));

        bytes = ByteKit.byteMerger(bytes, ByteKit.hexString2bytes(StringKit.string2hexString(唯一识别码)));
        logger.debug("唯一识别码=> {}", StringKit.bytes2hexString(ByteKit.hexString2bytes(StringKit.string2hexString(唯一识别码))));

        bytes = ByteKit.byteMerger(bytes, 数据单元加密方式.数据不加密);
        logger.debug("数据单元加密方式=> {}", StringKit.bytes2hexString(数据单元加密方式.数据不加密));

        byte[] data = 信息上报数据单元(timeString, zcsj, qddjsj, clwzsj, jzsj, bjsj, fdjsj);

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(data.length, 2));
        logger.debug("数据单元长度=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(data.length, 2)));

        bytes = ByteKit.byteMerger(bytes, data);//将数据单元合并到主byte数组中

        bytes = BBC(bytes);

        logger.debug("要发送的byte数组=> {}", bytes);
        logger.debug("hexString=> {}", StringKit.bytes2hexString(bytes));

        return bytes;
    }

    /**
     * 获得数据采集时间
     *
     * @param timeString yyyyMMddHHmmss
     * @return
     */
    public static byte[] 获得数据采集时间(String timeString) {
        byte[] time = new byte[6];
        int offset = 2;
        for (int i = 0; i < 6; i++) {
            time[i] = ByteKit.int2bytes(NumberKit.toInt(timeString.substring(offset, offset += 2)), 1)[0];
        }
        return time;
    }

    public static byte[] 信息上报数据单元(String timeString, 整车数据 zcsj, 驱动电机数据 qddjsj, 车辆位置数据 clwzsj, 极值数据 jzsj, 报警数据 bjsj, 发动机数据 fdjsj) {
        byte[] data = {};

        byte[] time = new byte[6];
        int offset = 2;
        for (int i = 0; i < 6; i++) {
            time[i] = ByteKit.int2bytes(NumberKit.toInt(timeString.substring(offset, offset += 2)), 1)[0];
        }
        data = ByteKit.byteMerger(data, time);
        logger.debug("信息上报数据单元-数据采集时间=> {}", StringKit.bytes2hexString(time));

        //信息上报数据单元
        if (zcsj != null) {
            data = ByteKit.byteMerger(data, 信息类型标识.整车数据);
            logger.debug("信息上报数据单元-信息类型标识=> {}", StringKit.bytes2hexString(信息类型标识.整车数据));

            data = ByteKit.byteMerger(data, zcsj.车辆状态);
            logger.debug("信息上报数据单元-整车数据信息体-车辆状态=> {}", StringKit.bytes2hexString(zcsj.车辆状态));
            data = ByteKit.byteMerger(data, zcsj.充电状态);
            logger.debug("信息上报数据单元-整车数据信息体-充电状态=> {}", StringKit.bytes2hexString(zcsj.充电状态));
            data = ByteKit.byteMerger(data, zcsj.运行模式);
            logger.debug("信息上报数据单元-整车数据信息体-运行模式=> {}", StringKit.bytes2hexString(zcsj.运行模式));
            data = ByteKit.byteMerger(data, zcsj.车速);
            logger.debug("信息上报数据单元-整车数据信息体-车速=> {}", StringKit.bytes2hexString(zcsj.车速));
            data = ByteKit.byteMerger(data, zcsj.累计里程);
            logger.debug("信息上报数据单元-整车数据信息体-累计里程=> {}", StringKit.bytes2hexString(zcsj.累计里程));
            data = ByteKit.byteMerger(data, zcsj.总电压);
            logger.debug("信息上报数据单元-整车数据信息体-总电压=> {}", StringKit.bytes2hexString(zcsj.总电压));
            data = ByteKit.byteMerger(data, zcsj.总电流);
            logger.debug("信息上报数据单元-整车数据信息体-总电流=> {}", StringKit.bytes2hexString(zcsj.总电流));
            data = ByteKit.byteMerger(data, zcsj.SOC);
            logger.debug("信息上报数据单元-整车数据信息体-SOC=> {}", StringKit.bytes2hexString(zcsj.SOC));
            data = ByteKit.byteMerger(data, zcsj.DC状态);
            logger.debug("信息上报数据单元-整车数据信息体-DC状态=> {}", StringKit.bytes2hexString(zcsj.DC状态));
            data = ByteKit.byteMerger(data, zcsj.档位);
            logger.debug("信息上报数据单元-整车数据信息体-档位=> {}", StringKit.bytes2hexString(zcsj.档位));
            data = ByteKit.byteMerger(data, zcsj.绝缘电阻);
            logger.debug("信息上报数据单元-整车数据信息体-绝缘电阻=> {}", StringKit.bytes2hexString(zcsj.绝缘电阻));
            data = ByteKit.byteMerger(data, zcsj.预留);
            logger.debug("信息上报数据单元-整车数据信息体-预留=> {}", StringKit.bytes2hexString(zcsj.预留));
        }

        if (qddjsj != null) {
            data = ByteKit.byteMerger(data, 信息类型标识.驱动电机数据);
            logger.debug("信息上报数据单元-信息类型标识=> {}", StringKit.bytes2hexString(信息类型标识.驱动电机数据));

            data = ByteKit.byteMerger(data, qddjsj.驱动电机个数);
            logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机个数=> {}", StringKit.bytes2hexString(qddjsj.驱动电机个数));

            //循环驱动电机总成信息列表
            for (驱动电机 qddj : qddjsj.驱动电机总成信息列表) {
                data = ByteKit.byteMerger(data, qddj.驱动电机序号);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-驱动电机序号=> {}", StringKit.bytes2hexString(qddj.驱动电机序号));

                data = ByteKit.byteMerger(data, qddj.驱动电机状态);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-驱动电机状态=> {}", StringKit.bytes2hexString(qddj.驱动电机状态));

                data = ByteKit.byteMerger(data, qddj.驱动电机控制器温度);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-驱动电机控制器温度=> {}", StringKit.bytes2hexString(qddj.驱动电机控制器温度));

                data = ByteKit.byteMerger(data, qddj.驱动电机转速);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-驱动电机转速=> {}", StringKit.bytes2hexString(qddj.驱动电机转速));

                data = ByteKit.byteMerger(data, qddj.驱动电机转矩);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-驱动电机转矩=> {}", StringKit.bytes2hexString(qddj.驱动电机转矩));

                data = ByteKit.byteMerger(data, qddj.驱动电机温度);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-驱动电机温度=> {}", StringKit.bytes2hexString(qddj.驱动电机温度));

                data = ByteKit.byteMerger(data, qddj.电机控制器输入电压);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-电机控制器输入电压=> {}", StringKit.bytes2hexString(qddj.电机控制器输入电压));

                data = ByteKit.byteMerger(data, qddj.电机控制器直流母线电流);
                logger.debug("信息上报数据单元-驱动电机数据信息-驱动电机总成信息列表-电机控制器直流母线电流=> {}", StringKit.bytes2hexString(qddj.电机控制器直流母线电流));
            }
        }

        if (clwzsj != null) {
            data = ByteKit.byteMerger(data, 信息类型标识.车辆位置数据);
            logger.debug("信息上报数据单元-信息类型标识=> {}", StringKit.bytes2hexString(信息类型标识.车辆位置数据));

            data = ByteKit.byteMerger(data, clwzsj.定位状态);
            logger.debug("信息上报数据单元-车辆位置数据-定位状态=> {}", StringKit.bytes2hexString(clwzsj.定位状态));

            data = ByteKit.byteMerger(data, clwzsj.经度);
            logger.debug("信息上报数据单元-车辆位置数据-经度=> {}", StringKit.bytes2hexString(clwzsj.经度));

            data = ByteKit.byteMerger(data, clwzsj.纬度);
            logger.debug("信息上报数据单元-车辆位置数据-纬度=> {}", StringKit.bytes2hexString(clwzsj.纬度));
        }

        if (jzsj != null) {
            data = ByteKit.byteMerger(data, 信息类型标识.极值数据);
            logger.debug("信息上报数据单元-信息类型标识=> {}", StringKit.bytes2hexString(信息类型标识.极值数据));

            data = ByteKit.byteMerger(data, jzsj.最高电压电池子系统号);
            logger.debug("信息上报数据单元-极值数据-最高电压电池子系统号=> {}", StringKit.bytes2hexString(jzsj.最高电压电池子系统号));

            data = ByteKit.byteMerger(data, jzsj.最高电压电池单体代号);
            logger.debug("信息上报数据单元-极值数据-最高电压电池单体代号=> {}", StringKit.bytes2hexString(jzsj.最高电压电池单体代号));

            data = ByteKit.byteMerger(data, jzsj.电池单体电压最高值);
            logger.debug("信息上报数据单元-极值数据-电池单体电压最高值=> {}", StringKit.bytes2hexString(jzsj.电池单体电压最高值));

            data = ByteKit.byteMerger(data, jzsj.最低电压电池子系统号);
            logger.debug("信息上报数据单元-极值数据-最低电压电池子系统号=> {}", StringKit.bytes2hexString(jzsj.最低电压电池子系统号));

            data = ByteKit.byteMerger(data, jzsj.最低电压电池单体号);
            logger.debug("信息上报数据单元-极值数据-最低电压电池单体号=> {}", StringKit.bytes2hexString(jzsj.最低电压电池单体号));

            data = ByteKit.byteMerger(data, jzsj.电池单体电压最低值);
            logger.debug("信息上报数据单元-极值数据-电池单体电压最低值=> {}", StringKit.bytes2hexString(jzsj.电池单体电压最低值));

            data = ByteKit.byteMerger(data, jzsj.最高温度子系统号);
            logger.debug("信息上报数据单元-极值数据-最高温度子系统号=> {}", StringKit.bytes2hexString(jzsj.最高温度子系统号));

            data = ByteKit.byteMerger(data, jzsj.最高温度探针序号);
            logger.debug("信息上报数据单元-极值数据-最高温度探针序号=> {}", StringKit.bytes2hexString(jzsj.最高温度探针序号));

            data = ByteKit.byteMerger(data, jzsj.最高温度值);
            logger.debug("信息上报数据单元-极值数据-最高温度值=> {}", StringKit.bytes2hexString(jzsj.最高温度值));

            data = ByteKit.byteMerger(data, jzsj.最低温度子系统号);
            logger.debug("信息上报数据单元-极值数据-最低温度子系统号=> {}", StringKit.bytes2hexString(jzsj.最低温度子系统号));

            data = ByteKit.byteMerger(data, jzsj.最低温度探针序号);
            logger.debug("信息上报数据单元-极值数据-最低温度探针序号=> {}", StringKit.bytes2hexString(jzsj.最低温度探针序号));

            data = ByteKit.byteMerger(data, jzsj.最低温度值);
            logger.debug("信息上报数据单元-极值数据-最低温度值=> {}", StringKit.bytes2hexString(jzsj.最低温度值));
        }

        if (bjsj != null) {
            data = ByteKit.byteMerger(data, 信息类型标识.报警数据);
            logger.debug("信息上报数据单元-报警数据=> {}", StringKit.bytes2hexString(信息类型标识.报警数据));

            data = ByteKit.byteMerger(data, bjsj.最高报警等级);
            logger.debug("信息上报数据单元-报警数据-最高报警等级=> {}", StringKit.bytes2hexString(bjsj.最高报警等级));

            data = ByteKit.byteMerger(data, bjsj.通用报警标识);
            logger.debug("信息上报数据单元-报警数据-通用报警标识=> {}", StringKit.bytes2hexString(bjsj.通用报警标识));

            data = ByteKit.byteMerger(data, bjsj.可充电储能装置故障总数N1);
            logger.debug("信息上报数据单元-报警数据-可充电储能装置故障总数N1=> {}", StringKit.bytes2hexString(bjsj.可充电储能装置故障总数N1));

            data = ByteKit.byteMerger(data, bjsj.可充电储能装置故障代码列表);
            logger.debug("信息上报数据单元-报警数据-可充电储能装置故障代码列表=> {}", StringKit.bytes2hexString(bjsj.可充电储能装置故障代码列表));

            data = ByteKit.byteMerger(data, bjsj.驱动电机故障总数N2);
            logger.debug("信息上报数据单元-报警数据-驱动电机故障总数N2=> {}", StringKit.bytes2hexString(bjsj.驱动电机故障总数N2));

            data = ByteKit.byteMerger(data, bjsj.驱动电机故障代码列表);
            logger.debug("信息上报数据单元-报警数据-驱动电机故障代码列表=> {}", StringKit.bytes2hexString(bjsj.驱动电机故障代码列表));

            data = ByteKit.byteMerger(data, bjsj.发动机故障总数N3);
            logger.debug("信息上报数据单元-报警数据-发动机故障总数N3=> {}", StringKit.bytes2hexString(bjsj.发动机故障总数N3));

            data = ByteKit.byteMerger(data, bjsj.发动机故障列表);
            logger.debug("信息上报数据单元-报警数据-发动机故障列表=> {}", StringKit.bytes2hexString(bjsj.发动机故障列表));

            data = ByteKit.byteMerger(data, bjsj.其他故障总数N4);
            logger.debug("信息上报数据单元-报警数据-其他故障总数N4=> {}", StringKit.bytes2hexString(bjsj.其他故障总数N4));

            data = ByteKit.byteMerger(data, bjsj.其他故障列表);
            logger.debug("信息上报数据单元-报警数据-其他故障列表=> {}", StringKit.bytes2hexString(bjsj.其他故障列表));
        }

        if (fdjsj != null) {
            data = ByteKit.byteMerger(data, 信息类型标识.发动机数据);
            logger.debug("信息上报数据单元-发动机数据=> {}", StringKit.bytes2hexString(信息类型标识.发动机数据));

            data = ByteKit.byteMerger(data, fdjsj.发动机状态);
            logger.debug("信息上报数据单元-发动机数据-发动机状态=> {}", StringKit.bytes2hexString(fdjsj.发动机状态));

            data = ByteKit.byteMerger(data, fdjsj.曲轴转速);
            logger.debug("信息上报数据单元-发动机数据-曲轴转速=> {}", StringKit.bytes2hexString(fdjsj.曲轴转速));

            data = ByteKit.byteMerger(data, fdjsj.燃料消耗率);
            logger.debug("信息上报数据单元-发动机数据-燃料消耗率=> {}", StringKit.bytes2hexString(fdjsj.燃料消耗率));
        }

        return data;
    }

    /**
     * 平台登出
     *
     * @param timeString 登出时间(yyyyMMddHHmmss)
     * @param loginNum   登出流水号(必须和登入流水号一致)
     * @return
     */
    public static byte[] 平台登出(String timeString, int loginNum) {
        byte[] bytes = {};

        bytes = ByteKit.byteMerger(bytes, 起始符.b0);
        logger.debug("起始符=> {}", StringKit.bytes2hexString(起始符.b0));

        bytes = ByteKit.byteMerger(bytes, 命令标识.平台登出);
        logger.debug("命令单元-命令标识=> {}", StringKit.bytes2hexString(命令标识.平台登出));

        bytes = ByteKit.byteMerger(bytes, 应答标识.命令);
        logger.debug("命令单元-应答标识=> {}", StringKit.bytes2hexString(应答标识.命令));

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(0, 17));
        logger.debug("唯一识别码=> {}", "平台登出不关心这项，所以使用0填充");

        bytes = ByteKit.byteMerger(bytes, 数据单元加密方式.数据不加密);
        logger.debug("数据单元加密方式=> {}", StringKit.bytes2hexString(数据单元加密方式.数据不加密));

        byte[] data = 平台登出数据单元(timeString, loginNum);

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(data.length, 2));
        logger.debug("数据单元长度=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(data.length, 2)));

        bytes = ByteKit.byteMerger(bytes, data);//将数据单元合并到主byte数组中

        bytes = BBC(bytes);

        logger.debug("要发送的byte数组=> {}", bytes);
        logger.debug("hexString=> {}", StringKit.bytes2hexString(bytes));

        return bytes;
    }

    /**
     * 平台登入
     *
     * @param timeString    时间(yyyyMMddHHmmss)
     * @param loginNum      登入流水号
     * @param loginName     平台登入名
     * @param loginPassword 平台登入密码
     * @return
     */
    public static byte[] 平台登入(String timeString, int loginNum, String loginName, String loginPassword) {
        byte[] bytes = {};

        bytes = ByteKit.byteMerger(bytes, 起始符.b0);
        logger.debug("起始符=> {}", StringKit.bytes2hexString(起始符.b0));

        bytes = ByteKit.byteMerger(bytes, 命令标识.平台登入);
        logger.debug("命令单元-命令标识=> {}", StringKit.bytes2hexString(命令标识.平台登入));

        bytes = ByteKit.byteMerger(bytes, 应答标识.命令);
        logger.debug("命令单元-应答标识=> {}", StringKit.bytes2hexString(应答标识.命令));

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(0, 17));
        logger.debug("唯一识别码=> {}", "平台登入不关心这项，所以使用0填充");

        bytes = ByteKit.byteMerger(bytes, 数据单元加密方式.数据不加密);
        logger.debug("数据单元加密方式=> {}", StringKit.bytes2hexString(数据单元加密方式.数据不加密));

        byte[] data = 平台登入数据单元(timeString, loginNum, loginName, loginPassword);

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(data.length, 2));
        logger.debug("数据单元长度=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(data.length, 2)));

        bytes = ByteKit.byteMerger(bytes, data);//将数据单元合并到主byte数组中

        bytes = BBC(bytes);

        logger.debug("要发送的byte数组=> {}", bytes);
        logger.debug("hexString=> {}", StringKit.bytes2hexString(bytes));

        return bytes;
    }


    /**
     * 车辆登入
     *
     * @param did        设备编号
     * @param timeString 数据采集时间(yyyyMMddHHmmss)
     * @param loginNum   登入流水号
     * @param ICCID      ICCID
     * @param n          可充电储能子系统数
     * @param m          可充电储能系统编码长度
     */
    public static byte[] 车辆登入(String did, String timeString, int loginNum, String ICCID, int n, int m) {
        byte[] bytes = {};

        bytes = ByteKit.byteMerger(bytes, 起始符.b0);
        logger.debug("起始符=> {}", StringKit.bytes2hexString(起始符.b0));

        bytes = ByteKit.byteMerger(bytes, 命令标识.车辆登入);
        logger.debug("命令单元-命令标识=> {}", StringKit.bytes2hexString(命令标识.车辆登入));

        bytes = ByteKit.byteMerger(bytes, 应答标识.命令);
        logger.debug("命令单元-应答标识=> {}", StringKit.bytes2hexString(应答标识.命令));

        bytes = ByteKit.byteMerger(bytes, ByteKit.hexString2bytes(StringKit.string2hexString(did)));
        logger.debug("唯一识别码=> {}", StringKit.bytes2hexString(ByteKit.hexString2bytes(StringKit.string2hexString(did))));

        bytes = ByteKit.byteMerger(bytes, 数据单元加密方式.数据不加密);
        logger.debug("数据单元加密方式=> {}", StringKit.bytes2hexString(数据单元加密方式.数据不加密));

        byte[] data = 车辆登入数据单元(timeString, loginNum, ICCID, n, m);

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(data.length, 2));
        logger.debug("数据单元长度=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(data.length, 2)));

        bytes = ByteKit.byteMerger(bytes, data);//将数据单元合并到主byte数组中

        bytes = BBC(bytes);

        logger.debug("要发送的byte数组=> {}", bytes);
        logger.debug("hexString=> {}", StringKit.bytes2hexString(bytes));

        return bytes;
    }

    /**
     * 车辆登出
     *
     * @param did        设备编号
     * @param timeString 登出时间(yyyyMMddHHmmss)
     * @param loginNum   登出流水号(必须和登入流水号一致)
     * @return
     */
    public static byte[] 车辆登出(String did, String timeString, int loginNum) {
        byte[] bytes = {};

        bytes = ByteKit.byteMerger(bytes, 起始符.b0);
        logger.debug("起始符=> {}", StringKit.bytes2hexString(起始符.b0));

        bytes = ByteKit.byteMerger(bytes, 命令标识.车辆登出);
        logger.debug("命令单元-命令标识=> {}", StringKit.bytes2hexString(命令标识.车辆登出));

        bytes = ByteKit.byteMerger(bytes, 应答标识.命令);
        logger.debug("命令单元-应答标识=> {}", StringKit.bytes2hexString(应答标识.命令));

        bytes = ByteKit.byteMerger(bytes, ByteKit.hexString2bytes(StringKit.string2hexString(did)));
        logger.debug("唯一识别码=> {}", StringKit.bytes2hexString(ByteKit.hexString2bytes(StringKit.string2hexString(did))));

        bytes = ByteKit.byteMerger(bytes, 数据单元加密方式.数据不加密);
        logger.debug("数据单元加密方式=> {}", StringKit.bytes2hexString(数据单元加密方式.数据不加密));

        byte[] data = 车辆登出数据单元(timeString, loginNum);

        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(data.length, 2));
        logger.debug("数据单元长度=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(data.length, 2)));

        bytes = ByteKit.byteMerger(bytes, data);//将数据单元合并到主byte数组中

        bytes = BBC(bytes);

        logger.debug("要发送的byte数组=> {}", bytes);
        logger.debug("hexString=> {}", StringKit.bytes2hexString(bytes));

        return bytes;
    }

    public static byte[] 车辆登出数据单元(String timeString, int loginNum) {
        byte[] data = {};

        byte[] time = new byte[6];
        int offset = 2;
        for (int i = 0; i < 6; i++) {
            time[i] = ByteKit.int2bytes(NumberKit.toInt(timeString.substring(offset, offset += 2)), 1)[0];
        }
        data = ByteKit.byteMerger(data, time);
        logger.debug("车辆登出数据单元-登出时间=> {}", StringKit.bytes2hexString(time));

        data = ByteKit.byteMerger(data, ByteKit.int2bytes(loginNum, 2));
        logger.debug("车辆登出数据单元-登出流水号=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(loginNum, 2)));

        return data;
    }

    public static byte[] BBC(byte[] bytes) {
        int bbc = 0;
        for (int i = 2; i < bytes.length; i++) {
            bbc ^= bytes[i];//异或校验
        }
        bytes = ByteKit.byteMerger(bytes, ByteKit.int2bytes(bbc, 1));
        logger.debug("校验码=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(bbc, 1)));
        return bytes;
    }

    public static byte[] 平台登入数据单元(String timeString, int loginNum, String loginName, String loginPassword) {
        byte[] data = {};

        byte[] time = new byte[6];
        int offset = 2;
        for (int i = 0; i < 6; i++) {
            time[i] = ByteKit.int2bytes(NumberKit.toInt(timeString.substring(offset, offset += 2)), 1)[0];
        }
        data = ByteKit.byteMerger(data, time);
        logger.debug("平台登入数据单元-平台登入时间=> {}", StringKit.bytes2hexString(time));

        data = ByteKit.byteMerger(data, ByteKit.int2bytes(loginNum, 2));
        logger.debug("平台登入数据单元-登入流水号=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(loginNum, 2)));

        data = ByteKit.byteMerger(data, ByteKit.hexString2bytes(StringKit.string2hexString(loginName)));
        logger.debug("平台登入数据单元-平台用户名=> {}", StringKit.string2hexString(loginName));

        data = ByteKit.byteMerger(data, ByteKit.hexString2bytes(StringKit.string2hexString(loginPassword)));
        logger.debug("平台登入数据单元-平台密码=> {}", StringKit.string2hexString(loginPassword));

        data = ByteKit.byteMerger(data, 数据单元加密方式.数据不加密);

        return data;
    }

    public static byte[] 平台登出数据单元(String timeString, int loginNum) {
        byte[] data = {};

        byte[] time = new byte[6];
        int offset = 2;
        for (int i = 0; i < 6; i++) {
            time[i] = ByteKit.int2bytes(NumberKit.toInt(timeString.substring(offset, offset += 2)), 1)[0];
        }
        data = ByteKit.byteMerger(data, time);
        logger.debug("平台登出数据单元-平台登出时间=> {}", StringKit.bytes2hexString(time));

        data = ByteKit.byteMerger(data, ByteKit.int2bytes(loginNum, 2));
        logger.debug("平台登出数据单元-登出流水号=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(loginNum, 2)));

        return data;
    }

    public static byte[] 车辆登入数据单元(String timeString, int loginNum, String ICCID, int n, int m) {
        byte[] data = {};

        byte[] time = new byte[6];
        int offset = 2;
        for (int i = 0; i < 6; i++) {
            time[i] = ByteKit.int2bytes(NumberKit.toInt(timeString.substring(offset, offset += 2)), 1)[0];
        }
        data = ByteKit.byteMerger(data, time);
        logger.debug("车辆登入数据单元-登入时间=> {}", StringKit.bytes2hexString(time));

        data = ByteKit.byteMerger(data, ByteKit.int2bytes(loginNum, 2));
        logger.debug("车辆登入数据单元-登入流水号=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(loginNum, 2)));

        data = ByteKit.byteMerger(data, ByteKit.hexString2bytes(StringKit.string2hexString(ICCID)));
        logger.debug("车辆登入数据单元-ICCID=> {}", StringKit.bytes2hexString(ByteKit.hexString2bytes(StringKit.string2hexString(ICCID))));

        data = ByteKit.byteMerger(data, ByteKit.int2bytes(n, 1));
        logger.debug("车辆登入数据单元-可充电储能子系统数=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(n, 1)));

        data = ByteKit.byteMerger(data, ByteKit.int2bytes(m, 1));
        logger.debug("车辆登入数据单元-可充电储能系统编码长度=> {}", StringKit.bytes2hexString(ByteKit.int2bytes(m, 1)));
        return data;
    }

    /**
     * 获得报文结构体
     *
     * @param hexString 16进制报文字符串
     * @return
     */
    public static 报文结构 获得报文结构(String hexString) {
        报文结构 bwjg = new 报文结构();
        数据单元 sjdy = new 数据单元();
        byte[] bytes = ByteKit.hexString2bytes(hexString);

        byte[] startFlag = ByteKit.getRange(bytes, 0, 2);
        bwjg.起始符 = startFlag;
        logger.debug("起始符 {}", StringKit.bytes2hexString(startFlag));

        byte[] commandType = ByteKit.getRange(bytes, 2, 1);
        bwjg.命令标识 = commandType;
        logger.debug("命令标识 {}", StringKit.bytes2hexString(commandType));

        byte[] answer = ByteKit.getRange(bytes, 3, 1);
        bwjg.应答标识 = answer;
        logger.debug("应答标识 {}", StringKit.bytes2hexString(answer));

        byte[] id = ByteKit.getRange(bytes, 4, 17);
        bwjg.唯一识别码 = id;
        //logger.debug("唯一识别码 {}", StringKit.bytes2hexString(id));
        logger.debug("唯一识别码 {}", StringKit.hexString2String(StringKit.bytes2hexString(id)));

        byte[] encrypt = ByteKit.getRange(bytes, 21, 1);
        bwjg.数据单元加密方式 = encrypt;
        logger.debug("数据单元加密方式 {}", StringKit.bytes2hexString(encrypt));

        byte[] dataLengthBytes = ByteKit.getRange(bytes, 22, 2);
        int dataLength = ByteKit.bytes2int(dataLengthBytes, 2);
        bwjg.数据单元长度 = dataLengthBytes;
        logger.debug("数据单元长度 {}", dataLength);

        byte[] data = ByteKit.getRange(bytes, 24, dataLength);
        fillDataUnit(commandType[0], data, sjdy);//填充数据单元对象
        bwjg.数据单元 = sjdy;
        logger.debug("数据单元 {}", StringKit.bytes2hexString(data));

        byte[] bcc = ByteKit.getRange(bytes, bytes.length - 1, 1);
        bwjg.校验码 = bcc;
        logger.debug("校验码 {}", StringKit.bytes2hexString(bcc));

        return bwjg;
    }

    private static void fillDataUnit(byte b, byte[] data, 数据单元 sjdy) {
        if (b == 1) {//车辆登入
            logger.debug("数据单元 车辆登入");
        } else if (b == 2) {//实时信息上报
            logger.debug("数据单元 实时信息上报");

            实时信息和补发信息数据单元(data, sjdy);
        } else if (b == 3) {//补发信息上报
            logger.debug("数据单元 补发信息上报");

            实时信息和补发信息数据单元(data, sjdy);
        } else if (b == 4) {//车辆登出
            logger.debug("数据单元 车辆登出");
        } else if (b == 5) {//平台登入
            logger.debug("数据单元 平台登入");
        } else if (b == 6) {//平台登出
            logger.debug("数据单元 平台登出");
        }
    }

    private static void 实时信息和补发信息数据单元(byte[] data, 数据单元 sjdy) {
        Can can = new Can();

        byte[] time = ByteKit.getRange(data, 0, 6);
        can.数据采集时间 = time;
        logger.debug("数据单元 实时信息上报 数据采集时间 {}", time);
        byte[] infos = ByteKit.getRange(data, 6);
        can.cans = infos;
        logger.debug("数据单元 实时信息上报 信息集合报文 {}", StringKit.bytes2hexString(infos));

        //循环所有信息体
        while (infos.length > 2) {
            byte[] infoType = ByteKit.getRange(infos, 0, 1);
            infos = ByteKit.getRange(infos, 1);
            if (infoType[0] == 1) {
                byte[] _data = ByteKit.getRange(infos, 0, 20);
                logger.debug("数据单元 实时信息上报 整车数据 报文 {}", StringKit.bytes2hexString(_data));
                infos = ByteKit.getRange(infos, 20);
            } else if (infoType[0] == 2) {
                byte[] _data = ByteKit.getRange(infos, 0, 1);
                int _num = ByteKit.bytes2int(_data, 1);
                _data = ByteKit.getRange(infos, 0, ((12 * _num) + 1));//一个电机12个长度
                logger.debug("数据单元 实时信息上报 驱动电机数据 报文 {}", StringKit.bytes2hexString(_data));
                infos = ByteKit.getRange(infos, ((12 * _num) + 1));
            } else if (infoType[0] == 3) {
                logger.debug("数据单元 实时信息上报 信息类型 {}", "燃料电池数据");
            } else if (infoType[0] == 4) {
                logger.debug("数据单元 实时信息上报 信息类型 {}", "发动机数据");
            } else if (infoType[0] == 5) {
                byte[] _data = ByteKit.getRange(infos, 0, 9);
                logger.debug("数据单元 实时信息上报 车辆位置数据 报文 {}", StringKit.bytes2hexString(_data));
                infos = ByteKit.getRange(infos, 9);
            } else if (infoType[0] == 6) {
                byte[] _data = ByteKit.getRange(infos, 0, 14);
                logger.debug("数据单元 实时信息上报 极值数据 报文 {}", StringKit.bytes2hexString(_data));
                infos = ByteKit.getRange(infos, 14);
            } else if (infoType[0] == 7) {
                byte[] _data = new byte[0];

                _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, 1));//最高报警等级
                infos = ByteKit.getRange(infos, 1);

                _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, 4));//通用报警标识
                infos = ByteKit.getRange(infos, 4);

                byte[] n1 = ByteKit.getRange(infos, 0, 1);//可充电储能装置故障总数
                int n1Num = ByteKit.bytes2int(n1, 1);
                _data = ByteKit.byteMerger(_data, n1);//可充电储能装置故障N1
                infos = ByteKit.getRange(infos, 1);

                _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, (4 * n1Num)));//可充电储能装置故障代码列表4*N1长度
                infos = ByteKit.getRange(infos, (4 * n1Num));

                byte[] n2 = ByteKit.getRange(infos, 0, 1);//驱动电机故障总数
                int n2Num = ByteKit.bytes2int(n2, 1);
                _data = ByteKit.byteMerger(_data, n2);//驱动电机故障总数N2
                infos = ByteKit.getRange(infos, 1);

                _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, (4 * n2Num)));//驱动电机故障代码列表4*N2长度
                infos = ByteKit.getRange(infos, (4 * n2Num));

                byte[] n3 = ByteKit.getRange(infos, 0, 1);//发动机故障总数
                int n3Num = ByteKit.bytes2int(n3, 1);
                _data = ByteKit.byteMerger(_data, n3);//发动机故障总数n3
                infos = ByteKit.getRange(infos, 1);

                _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, (4 * n3Num)));//发动机故障代码列表4*n3长度
                infos = ByteKit.getRange(infos, (4 * n3Num));

                byte[] n4 = ByteKit.getRange(infos, 0, 1);//其他故障总数
                int n4Num = ByteKit.bytes2int(n4, 1);
                _data = ByteKit.byteMerger(_data, n4);//其他故障总数n4
                infos = ByteKit.getRange(infos, 1);

                _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, (4 * n4Num)));//其他故障代码列表4*n4长度
                infos = ByteKit.getRange(infos, (4 * n4Num));

                logger.debug("数据单元 实时信息上报 报警数据 报文 {}", StringKit.bytes2hexString(_data));
            } else if (infoType[0] == 8) {
                byte[] _data = new byte[0];

                byte[] n = ByteKit.getRange(infos, 0, 1);//可充电储能子系统个数
                int nNum = ByteKit.bytes2int(n, 1);
                _data = ByteKit.byteMerger(_data, n);
                infos = ByteKit.getRange(infos, 1);

                for (int i = 0; i < nNum; i++) {
                    _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, 9));
                    infos = ByteKit.getRange(infos, 9);

                    byte[] m = ByteKit.getRange(infos, 0, 1);//本帧单体电池总数
                    int mNum = ByteKit.bytes2int(m, 1);
                    _data = ByteKit.byteMerger(_data, m);
                    infos = ByteKit.getRange(infos, 1);

                    _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, (2 * mNum)));//单体电池电压
                    infos = ByteKit.getRange(infos, (2 * mNum));
                }

                logger.debug("数据单元 实时信息上报 可充电储能装置电压数据 报文 {}", StringKit.bytes2hexString(_data));
            } else if (infoType[0] == 9) {
                byte[] _data = new byte[0];

                byte[] n = ByteKit.getRange(infos, 0, 1);//可充电储能子系统个数
                int nNum = ByteKit.bytes2int(n, 1);
                _data = ByteKit.byteMerger(_data, n);
                infos = ByteKit.getRange(infos, 1);

                for (int i = 0; i < nNum; i++) {
                    _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, 1));//可充电储能子系统号
                    infos = ByteKit.getRange(infos, 1);

                    byte[] k = ByteKit.getRange(infos, 0, 2);//可充电储能温度探针个数
                    int kNum = ByteKit.bytes2int(k, 2);
                    _data = ByteKit.byteMerger(_data, k);
                    infos = ByteKit.getRange(infos, 2);

                    _data = ByteKit.byteMerger(_data, ByteKit.getRange(infos, 0, (1 * kNum)));
                    infos = ByteKit.getRange(infos, (1 * kNum));
                }

                logger.debug("数据单元 实时信息上报 可充电储能装置温度数据 报文 {}", StringKit.bytes2hexString(_data));
            }
        }

        sjdy.实时信息上报 = can;
        sjdy.补发信息上报 = can;
    }
}

class 报文结构 {
    public byte[] 起始符;
    public byte[] 命令标识;
    public byte[] 应答标识;
    public byte[] 唯一识别码;
    public byte[] 数据单元加密方式;
    public byte[] 数据单元长度;
    public 数据单元 数据单元;
    public byte[] 校验码;
}

class 数据单元 {
    public byte[] 车辆登入;
    public Can 实时信息上报;
    public Can 补发信息上报;
    public byte[] 车辆登出;
    public byte[] 平台登入;
    public byte[] 平台登出;
}

class Can {
    public byte[] 数据采集时间;
    public byte[] cans;
}

class 起始符 {
    public static final byte[] b0 = {0x23, 0x23};
}

class 命令标识 {
    public static final byte[] 车辆登入 = {0x01};
    public static final byte[] 实时信息上报 = {0x02};
    public static final byte[] 补发信息上报 = {0x03};
    public static final byte[] 车辆登出 = {0x04};
    public static final byte[] 平台登入 = {0x05};
    public static final byte[] 平台登出 = {0x06};
}

class 应答标识 {
    public static final byte[] 成功 = {0x01};
    public static final byte[] 错误 = {0x02};
    public static final byte[] VIN重复 = {0x03};
    public static final byte[] 命令 = {(byte) 0xFE};
}

class 数据单元加密方式 {
    public static final byte[] 数据不加密 = {0x01};
    public static final byte[] 数据经过RSA算法加密 = {0x02};
    public static final byte[] 数据经过AES128位算法加密 = {0x03};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 信息类型标识 {
    public static final byte[] 整车数据 = {0x01};
    public static final byte[] 驱动电机数据 = {0x02};
    public static final byte[] 燃料电池数据 = {0x03};
    public static final byte[] 发动机数据 = {0x04};
    public static final byte[] 车辆位置数据 = {0x05};
    public static final byte[] 极值数据 = {0x06};
    public static final byte[] 报警数据 = {0x07};
}

class 整车数据 {
    public byte[] 车辆状态 = {0x02};
    public byte[] 充电状态 = {0x03};
    public byte[] 运行模式 = {0x01};
    public byte[] 车速 = {0x00, 0x00};
    public byte[] 累计里程 = {0x00, 0x00, 0x00, 0x00};
    public byte[] 总电压 = {0x00, 0x00};
    public byte[] 总电流 = {0x00, 0x00};
    public byte[] SOC = {0x00};
    public byte[] DC状态 = {0x02};
    public byte[] 档位 = {0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01};
    public byte[] 绝缘电阻 = {0x00, 0x00};
    public byte[] 预留 = {0x00, 0x00};
}

class 档位 {
    public static final byte[] 有驱动力无制动力空挡 = {0x20};
    public static final byte[] 有驱动力无制动力1挡 = {0x21};
    public static final byte[] 有驱动力无制动力2挡 = {0x22};
    public static final byte[] 有驱动力无制动力3挡 = {0x23};
    public static final byte[] 有驱动力无制动力4挡 = {0x24};
    public static final byte[] 有驱动力无制动力5挡 = {0x25};
    public static final byte[] 有驱动力无制动力6挡 = {0x26};
    public static final byte[] 有驱动力无制动力倒挡 = {0x2D};
    public static final byte[] 有驱动力无制动力D挡 = {0x2E};
    public static final byte[] 有驱动力无制动力P挡 = {0x2F};
}

class DC状态 {
    public static final byte[] 工作 = {0x01};
    public static final byte[] 断开 = {0x02};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 运行模式 {
    public static final byte[] 纯电 = {0x01};
    public static final byte[] 混动 = {0x02};
    public static final byte[] 燃油 = {0x03};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 车辆状态 {
    public static final byte[] 车辆启动状态 = {0x01};
    public static final byte[] 熄火 = {0x02};
    public static final byte[] 其他状态 = {0x03};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 标识无效 = {(byte) 0xFF};
}

class 充电状态 {
    public static final byte[] 停车充电 = {0x01};
    public static final byte[] 行驶充电 = {0x02};
    public static final byte[] 未充电状态 = {0x03};
    public static final byte[] 充电完成 = {0x04};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 驱动电机数据 {
    public byte[] 驱动电机个数 = {0x01};
    public List<驱动电机> 驱动电机总成信息列表 = new ArrayList<>();
}

class 驱动电机 {
    public byte[] 驱动电机序号 = {0x01};
    public byte[] 驱动电机状态 = {0x03};
    public byte[] 驱动电机控制器温度 = {0x00};
    public byte[] 驱动电机转速 = {0x00, 0x00};
    public byte[] 驱动电机转矩 = {0x00, 0x00};
    public byte[] 驱动电机温度 = {0x00};
    public byte[] 电机控制器输入电压 = {0x00, 0x00};
    public byte[] 电机控制器直流母线电流 = {0x00, 0x00};
}

class 驱动电机状态 {
    public static final byte[] 耗电 = {0x01};
    public static final byte[] 发电 = {0x02};
    public static final byte[] 关闭状态 = {0x03};
    public static final byte[] 准备状态 = {0x04};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 车辆位置数据 {
    public byte[] 定位状态 = {0x00};
    public byte[] 经度 = {0x00, 0x00, 0x00, 0x00};
    public byte[] 纬度 = {0x00, 0x00, 0x00, 0x00};
}

class 定位状态 {
    public byte[] data = new byte[1];

    public 定位状态(int 有效定位0无效定位1, int 北纬0南纬1, int 东经0西经1) {
        String b0 = "00000" + 东经0西经1 + 北纬0南纬1 + 有效定位0无效定位1;
        data[0] = (byte) Integer.parseInt(b0, 2);
    }
}

class 极值数据 {
    public byte[] 最高电压电池子系统号 = {0x01};
    public byte[] 最高电压电池单体代号 = {0x01};
    public byte[] 电池单体电压最高值 = {0x00, 0x00};
    public byte[] 最低电压电池子系统号 = {0x01};
    public byte[] 最低电压电池单体号 = {0x01};
    public byte[] 电池单体电压最低值 = {0x00, 0x00};
    public byte[] 最高温度子系统号 = {0x01};
    public byte[] 最高温度探针序号 = {0x01};
    public byte[] 最高温度值 = {0x00};
    public byte[] 最低温度子系统号 = {0x01};
    public byte[] 最低温度探针序号 = {0x01};
    public byte[] 最低温度值 = {0x00};
}

class 报警数据 {
    public byte[] 最高报警等级 = {0x00};
    public byte[] 通用报警标识 = ByteKit.int2bytes(0, 4);
    public byte[] 可充电储能装置故障总数N1 = {0X00};
    public byte[] 可充电储能装置故障代码列表 = ByteKit.int2bytes(0, 4 * 可充电储能装置故障总数N1.length);
    public byte[] 驱动电机故障总数N2 = {0x00};
    public byte[] 驱动电机故障代码列表 = ByteKit.int2bytes(0, 4 * 驱动电机故障总数N2.length);
    public byte[] 发动机故障总数N3 = {0x00};
    public byte[] 发动机故障列表 = ByteKit.int2bytes(0, 4 * 发动机故障总数N3.length);
    public byte[] 其他故障总数N4 = {0x00};
    public byte[] 其他故障列表 = ByteKit.int2bytes(0, 4 * 其他故障总数N4.length);
}

class 发动机数据 {
    public byte[] 发动机状态 = {0x02};
    public byte[] 曲轴转速 = {0x00, 0x00};
    public byte[] 燃料消耗率 = {0x00, 0x00};
}

class 发动机状态 {
    public static final byte[] 启动状态 = {0x01};
    public static final byte[] 关闭状态 = {0x02};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 通用报警标识 {
    public byte[] data = new byte[4];

    /**
     * 0代表正常，1代表报警
     *
     * @param 温度差异报警
     * @param 电池高温报警
     * @param 车载储能装置类型过压报警
     * @param 车载储能装置类型欠压报警
     * @param SOC低报警
     * @param 单体电池过压报警
     * @param 单体电池欠压报警
     * @param SOC过高报警
     * @param SOC跳变报警
     * @param 可充电储能系统不匹配报警
     * @param 电池体一致性差报警
     * @param 绝缘报警
     * @param DC温度报警
     * @param 制动系统报警
     * @param DC状态报警
     * @param 驱动电机控制器温度报警
     * @param 高压互锁状态报警
     * @param 驱动电机温度报警
     * @param 车载储能装置类型过充
     */
    public 通用报警标识(int 温度差异报警
            , int 电池高温报警
            , int 车载储能装置类型过压报警
            , int 车载储能装置类型欠压报警
            , int SOC低报警
            , int 单体电池过压报警
            , int 单体电池欠压报警
            , int SOC过高报警
            , int SOC跳变报警
            , int 可充电储能系统不匹配报警
            , int 电池体一致性差报警
            , int 绝缘报警
            , int DC温度报警
            , int 制动系统报警
            , int DC状态报警
            , int 驱动电机控制器温度报警
            , int 高压互锁状态报警
            , int 驱动电机温度报警
            , int 车载储能装置类型过充) {
        String b0 = "00000000";
        data[0] = (byte) Integer.parseInt(b0, 2);
        String b1 = "00000" + 车载储能装置类型过充 + 驱动电机温度报警 + 高压互锁状态报警;
        data[1] = (byte) Integer.parseInt(b1, 2);
        String b2 = "" + 驱动电机控制器温度报警 + DC状态报警 + 制动系统报警 + DC温度报警 + 绝缘报警 + 电池体一致性差报警 + 可充电储能系统不匹配报警 + SOC跳变报警;
        data[2] = (byte) Integer.parseInt(b2, 2);
        String b3 = "" + SOC过高报警 + 单体电池欠压报警 + 单体电池过压报警 + SOC低报警 + 车载储能装置类型欠压报警 + 车载储能装置类型过压报警 + 电池高温报警 + 温度差异报警;
        data[3] = (byte) Integer.parseInt(b3, 2);
    }
}

class 最高报警等级 {
    public static final byte[] 无故障 = {0x00};
    public static final byte[] 一级故障 = {0x01};
    public static final byte[] 二级故障 = {0x02};
    public static final byte[] 三级故障 = {0x03};
    public static final byte[] 表示异常 = {(byte) 0xFE};
    public static final byte[] 表示无效 = {(byte) 0xFF};
}

class 燃料电池数据 {
    public byte[] 燃料电池电压 = ByteKit.int2bytes(0, 2);
    public byte[] 燃料电池电流 = ByteKit.int2bytes(0, 2);
    public byte[] 燃料消耗率 = ByteKit.int2bytes(0, 2);
    public byte[] 燃料电池温度探针总数 = ByteKit.int2bytes(0, 2);
}

